package com.mirror.tk.web.controller.user;

import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.google.common.collect.Maps;
import com.mirror.tk.core.module.user.domain.User;
import com.mirror.tk.core.module.user.domain.UserPid;
import com.mirror.tk.core.module.user.service.UserPidService;
import com.mirror.tk.core.module.user.service.UserService;
import com.mirror.tk.framework.common.exception.BusinessException;
import com.mirror.tk.framework.common.web.support.JsonResult;
import com.mirror.tk.security.support.Cryptos;
import com.mirror.tk.web.common.Constant;
import com.mirror.tk.web.common.support.SessionFace;
import com.mirror.tk.web.common.support.SessionUser;
import com.mirror.tk.web.controller.CommonController;

/**
 * 用户相关controller
 */
@Controller
public class UserController extends CommonController {

	private static final String USER_LOGIN = "user/login";
	private static final String USER_REGSITER = "user/register";
	private static final String USER_FIND_PWD = "user/find_pwd";
	private static final String USER_UPDATE_PWD = "user/update_pwd";
	private static final String USER_PID = "user/pid";
	private static final String USER_PID_CREATE = "user/pid_create";
	private static final String USER_INFO = "user/info";
	
	int HASH_INTERATIONS = 1024;
	int SALT_SIZE = 8;
	int TYPE_REGISERT = 1;
	int TYPE_FIND_PWD = 2;
	String FLAG_FIND_PWD = "find_pwd";
	String FLAG_REGISTER = "register";
	String VERIFICATION_CODE = "verification_code_%s";
	String USER_PHONE_CODE = "user_phone_code";
	
	@Resource
	private UserService userService;
	@Resource
	private UserPidService userPidService;
	
	/**
	 * 获取用户信息（首页展示）
	 * @return
	 */
	@RequestMapping(value = "userInfo", method = RequestMethod.GET)
	public String userInfo(HttpServletRequest request, ModelMap map){
		// 如果已经登陆，将用户信息放入map
		if(SessionFace.isUserLogin(request)){
			map.put("su", SessionFace.getSessionUser(request));
		}
		return USER_INFO;
	}
	
	/**
	 * 发送短信
	 * @param request
	 * @param phone
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "sendSMS", method = RequestMethod.POST)
	public JsonResult sendSMS(HttpServletRequest request, 
			@RequestParam(value = "type", required = true)Integer type,
			@RequestParam(value = "phone", required = true)String phone){
		JsonResult result = new JsonResult(false);
		String code = StringUtils.right(Long.toString(System.currentTimeMillis()), 6);
		//TODO 发送验证码逻辑
		// 将验证码信息放入session，以便后续验证
		SessionFace.setAttribute(request, String.format(VERIFICATION_CODE, type == 1 ? FLAG_REGISTER : FLAG_FIND_PWD), code);
		logger.debug("code:{}", code);
		result.setMessage("发送成功，请注意查收！");
		return result;
	}
	
	/**
	 * 登陆
	 * @param request
	 * @return
	 */
	@RequestMapping(value = "login", method = RequestMethod.GET)
	public String login(HttpServletRequest request, ModelMap map){
		// 获取登陆请求来源，以便登陆后跳转回去
		String ref = null == request.getHeader("Referer") ? "index" : request.getHeader("Referer");
		// 如果用户已经登陆过了，提示不需要重复登陆
		/*if(SessionFace.isUserLogin(request)){
			return ref;
		}*/
		map.put("ref", ref);
		return USER_LOGIN;
	}
	
	/**
	 * 登陆
	 * @param request
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "login", method = RequestMethod.POST)
	public JsonResult login(HttpServletRequest request, 
			@RequestParam(value = "phone", required = true)String phone,
			@RequestParam(value = "password", required = true)String password){
		JsonResult result = new JsonResult(false);
		User user = userService.getUserByPhone(phone);
		if(null != user && validatePassword(user, password)){
			SessionUser sessionUser = SessionUser.bulider(user);
			SessionFace.setSessionUser(request, sessionUser);
			result.setSuccess(true);
			result.setCode(Constant.Global.SUCCESS);
			result.setMessage(Constant.UserMassage.USER_LOGIN_SUCCESS);
			return result;
		}
		result.setCode(Constant.Global.FAIL);
		result.setMessage(Constant.UserMassage.USER_LOGIN_FAIL);
		return result;
	}
	
	/**
	 * 退出登陆
	 * @param request
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "logout", method = RequestMethod.GET)
	public JsonResult logout(HttpServletRequest request){
		JsonResult result = new JsonResult(SessionFace.logout(request));
		return result;
	}
	
	/**
	 * 找回密码
	 * @param request
	 * @return
	 */
	@RequestMapping(value = "findPwd", method = RequestMethod.GET)
	public String findPwd(HttpServletRequest request){
		return USER_FIND_PWD;
	}

	/**
	 * 找回密码
	 * @param request
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "findPwd", method = RequestMethod.POST)
	public JsonResult ajaxFindPwd(HttpServletRequest request, 
			@RequestParam(value = "newPwd", required = true)String newPwd){
		JsonResult result = new JsonResult(false);
		if(null != SessionFace.getAttribute(request, FLAG_FIND_PWD)){
			// 从缓存取而不从前台读取，避免修改他人密码
			String phone = String.valueOf(SessionFace.getAttribute(request, USER_PHONE_CODE));
			User user = userService.getUserByPhone(phone);
			user.setPassword(newPwd);
			entryptPassword(user);
			user.setUpdateTime(new Date());
			try {
				userService.update(user);
			} catch (Exception e) {
				result.setCode(Constant.Global.FAIL);
				result.setMessage(Constant.UserMassage.USER_FIND_PWD_FAIL);
				return result;
			}
			result.setSuccess(true);
			result.setCode(Constant.Global.SUCCESS);
			result.setMessage(Constant.UserMassage.USER_FIND_PWD_SUCCESS);
			return result;
		}
		result.setCode(Constant.Global.FAIL);
		result.setMessage(Constant.Global.ILLEGAL_ACCESS);
		return result;
	}
	
	/**
	 * 检查验证码
	 * @param request
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "checkVC", method = RequestMethod.POST)
	public JsonResult checkVerificationCode(HttpServletRequest request, 
			@RequestParam(value = "phone", required = true)String phone,
			@RequestParam(value = "code", required = true)String code){
		JsonResult result = new JsonResult(false);
		// 验证用户是否存在
		if(!userisExisted(phone)){
			result.setCode(Constant.Global.FAIL);
			result.setMessage(Constant.UserMassage.USER_IS_NOT_EXISTED);
			return result;
		}
		// 验证验证码
		if(code.equalsIgnoreCase(String.valueOf(SessionFace.getAttribute(request, String.format(VERIFICATION_CODE, FLAG_FIND_PWD))))){
			// 将电话号码和标识放入session，避免二次传参攻击
			SessionFace.setAttribute(request, USER_PHONE_CODE, phone);
			SessionFace.setAttribute(request, FLAG_FIND_PWD, true);
			result.setSuccess(true);
			result.setCode(Constant.Global.SUCCESS);
			return result;
		}
		result.setCode(Constant.Global.FAIL);
		result.setMessage(Constant.UserMassage.USER_VERIFICATION_CODE_ERROR);
		return result;
	}
	
	/**
	 * 找回密码 发送短信
	 * @param request
	 * @param phone
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "findPwdv", method = RequestMethod.POST)
	public JsonResult validateSMS(HttpServletRequest request, 
			@RequestParam(value = "phone", required = true)String phone,
			@RequestParam(value = "code", required = true)String code){
		JsonResult result = new JsonResult(false);
		//TODO 验证验证码逻辑
		return result;
	}
	
	/**
	 * 注册
	 * @param request
	 * @return
	 */
	@RequestMapping(value = "register", method = RequestMethod.GET)
	public String register(HttpServletRequest request){
		return USER_REGSITER;
	}
	
	/**
	 * 注册
	 * @param request
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "register", method = RequestMethod.POST)
	public JsonResult postRegister(HttpServletRequest request, User user, 
			@RequestParam(value = "code", required = true)String code){
		JsonResult result = new JsonResult(false);
		// 验证验证码
		if(!code.equalsIgnoreCase(String.valueOf(SessionFace.getAttribute(request, String.format(VERIFICATION_CODE, FLAG_REGISTER))))){
			result.setCode(Constant.Global.FAIL);
			result.setMessage(Constant.UserMassage.USER_VERIFICATION_CODE_ERROR);
			return result;
		}
		// 再次检查用户名是否存在于系统中
		if(!userisExisted(user.getUsername())){
			user.setCreateTime(new Date());
			entryptPassword(user);
			try {
				userService.save(user);
			} catch (Exception e) {
				result.setCode(Constant.Global.FAIL);
				result.setMessage(Constant.UserMassage.USER_REGIEST_FAILE);
				return result;
			}
			result.setSuccess(true);
			result.setCode(Constant.Global.SUCCESS);
			result.setMessage(Constant.UserMassage.USER_REGIEST_SUCCESS);
			return result;
		}
		result.setCode(Constant.Global.FAIL);
		result.setMessage(Constant.UserMassage.USER_IS_EXISTED);
		return result;
	}
	
	/**
	 * 修改密码
	 * @param request
	 * @return
	 */
	@RequestMapping(value = "updatePwd", method = RequestMethod.GET)
	public String updatePwd(HttpServletRequest request){
		return USER_UPDATE_PWD;
	}
	
	/**
	 * 修改密码
	 * @param request
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "updatePwd", method = RequestMethod.POST)
	public JsonResult ajaxUptatePwd(HttpServletRequest request,
			@RequestParam(value = "oldPwd", required = true)String oldPwd,
			@RequestParam(value = "newPwd", required = true)String newPwd){
		JsonResult result = new JsonResult(false);
		User user = userService.get(SessionFace.getSessionUser(request).getId());
		if(null == user){
			result.setCode(Constant.Global.FAIL);
			result.setMessage(Constant.UserMassage.USER_IS_NOT_EXISTED);
			return result;
		}
		// 检查原密码是否正确
		boolean b = validatePassword(user, oldPwd);
		if (b) {
			user.setPassword(newPwd);
			entryptPassword(user);
			userService.save(user);
			result.setSuccess(true);
			result.setCode(Constant.Global.SUCCESS);
			result.setMessage(Constant.UserMassage.USER_UPDATE_PWD_SUCCESS);
			return result;
		} else {
			result.setCode(Constant.Global.FAIL);
			result.setMessage(Constant.UserMassage.USER_PWD_ERROR);
			return result;
		}
	}
	
	/**
	 * 获取pid列表
	 * @param request
	 * @return
	 */
	@RequestMapping(value = "pid", method = RequestMethod.GET)
	public String pid(HttpServletRequest request, ModelMap map){
		// 获取pid列表
		map.put("pids", userPidService.getByUserId(SessionFace.getSessionUser(request).getId()));
		return USER_PID;
	}
	
	/**
	 * 增加/修改pid
	 * @return
	 */
	@RequestMapping(value = "editPid", method = RequestMethod.GET)
	public String editPid(HttpServletRequest request, ModelMap map, Long id){
		// 如果带ID则为修改pid
		if(null != id){
			map.put("pid", userPidService.getByUserIdAndId(id, SessionFace.getSessionUser(request).getId()));
		}
		return USER_PID_CREATE;
	}
	
	/**
	 * 增加/修改pid
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "editPid", method = RequestMethod.POST)
	public JsonResult ajaxEditPid(HttpServletRequest request, UserPid pid){
		JsonResult result = new JsonResult(false);
		if(pid!= null && null != pid.getId()){
			// 修改保存
			UserPid oPid = userPidService.getByUserIdAndId(pid.getId(), SessionFace.getSessionUser(request).getId());
			if(null == oPid){
				result.setCode(Constant.Global.FAIL);
				result.setMessage(Constant.UserMassage.USER_PID_NOT_EXISTED);
				return result;
			}
			oPid.setName(pid.getName());
			oPid.setCommonPid(pid.getCommonPid());
			oPid.setQueqiaoPid(pid.getQueqiaoPid());
			oPid.setUpdateTime(new Date());
			userPidService.update(oPid);
		} else {
			// 增加
			pid.setUserId(SessionFace.getSessionUser(request).getId());
			pid.setCreateTime(new Date());
			pid.setUpdateTime(new Date());
			userPidService.save(pid);
		}
		result.setSuccess(true);
		result.setCode(Constant.Global.SUCCESS);
		return result;
	}
	
	/**
	 * 删除pid
	 * @param request
	 * @param id
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "pid/{id}", method = RequestMethod.POST)
	public JsonResult delPid(HttpServletRequest request,@PathVariable Long id){
		JsonResult result = new JsonResult(true);
		UserPid pid = userPidService.getByUserIdAndId(id, SessionFace.getSessionUser(request).getId());
		if(null == pid){
			result.setCode(Constant.Global.FAIL);
			result.setMessage(Constant.UserMassage.USER_PID_NOT_EXISTED);
			return result;
		}
		userPidService.remove(pid);
		result.setSuccess(true);
		result.setCode(Constant.Global.SUCCESS);
		return result;
	}
	
	/**
	 * 检查用户是否存在
	 * @param userName
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "isExisted", method = RequestMethod.GET)
	public Boolean isExisted(@RequestParam(value = "phone", required = true)String phone){
		return !userisExisted(phone);
	}
	
	/**
	 * 检查用户是否在系统中存在
	 * @param userName
	 * @return
	 */
	private Boolean userisExisted(String phone){
		if(StringUtils.isNotBlank(phone)){
			Map<String, Object> map = Maps.newHashMap();
			map.put("EQ_phone", phone);
			List<User> userList = userService.query(map, null);
			if(null != userList && !userList.isEmpty()){
				return true;
			}
		}
		return false;
	}
	
	/**
	 * 验证加密后的密码是否相同
	 * 
	 * @param user
	 * @param plaintPassword
	 * @return
	 * @throws BusinessException
	 */
	public boolean validatePassword(User user, String plaintPassword) throws BusinessException {
		return entryptPassword(plaintPassword, user.getSalt()).equals(user.getPassword());
	}

	/**
	 * 设定安全的密码，生成随机的salt并经过1024次 sha-1 hash
	 * 
	 * @param user
	 */
	private void entryptPassword(User user) {
		user.setSalt(Cryptos.generatorSalt(SALT_SIZE));
		user.setPassword(Cryptos.sha1(user.getPassword(), user.getSalt(), HASH_INTERATIONS));
	}
	
	private String entryptPassword(String plainPassword, String salt) {
		return Cryptos.sha1(plainPassword, salt, HASH_INTERATIONS);
	}
	
}